/**  
 * @Title: FlowService.java
 * @Description: TODO(描述)
 * @author liuyi
 * @date 2023-03-23 15:09:58 
 */
package com.fsxgt.datagrid.core.task;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang3.SerializationUtils;

import com.fsxgt.datagrid.core.exception.DataGridException;
import com.fsxgt.datagrid.core.utils.LogHelpper;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TaskContainer {

	private static final AtomicInteger index = new AtomicInteger(1);

	private Executor mainPool;

	private static TaskContainer instance;

	public static TaskContainer getInstance(Integer threadSize) {
		// 这个条件用于判断是否要加锁
		// 如果对象已经有了，就不必加锁了，此时本身就是线程安全的
		if (instance == null) {
			synchronized (TaskContainer.class) {
				if (instance == null) {
					instance = new TaskContainer(threadSize);
				}
			}
		}
		return instance;
	}
	
	public static void main(String args[]) throws DataGridException, InterruptedException {
		
		TaskContainer container = TaskContainer.getInstance(2);
		
		Task task=new Task("1","test");
		
		task.addSubTask(new SubTask("a","a") {

			@Override
			public TaskReturn handler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				Thread.sleep(3000);
				log.info("完成"+this.getName());
				return new TaskReturn();
			}

			@Override
			public void stopHandler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				
			}
		});
		task.addSubTask(new SubTask("b","b") {

			@Override
			public TaskReturn handler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				Thread.sleep(6000);
				log.info("完成"+this.getName());
				
				return new TaskReturn();
			}

			@Override
			public void stopHandler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				
			}
			
		});
		
		SubTask ctask = new SubTask("c","c") {

			@Override
			public TaskReturn handler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				Thread.sleep(3000);
				log.info("完成"+this.getName());
				return new TaskReturn();
			}

			@Override
			public void stopHandler(TaskContext context) throws Exception {
				// TODO Auto-generated method stub
				
			}
		};
		
		task.addChildSubTask("a", ctask);
		task.addChildSubTask("b", ctask);
		
		TaskRunParam param=new TaskRunParam("123", "C:\\61\\log\\111.log", 2, null,null);

		container.execute( task, new TaskContext(),param,new TaskCallback() {

			@Override
			public void handler(Date startTime, Date overTime, String status, String logPath, String execId) {
				// TODO Auto-generated method stub
				System.out.println("over");
				System.exit(0);
			}
			
		});
		Thread.sleep(4000);
		task.shutdownNow();
		
		

	}

	private class TaskRunnable implements Runnable {


		private Task task;
		private TaskContext context;
		private TaskCallback taskCallback;
		private TaskRunParam taskRunParam;


		public TaskRunnable( Task task, TaskContext context,
				TaskRunParam taskRunParam,TaskCallback taskCallback) {

			this.task = task;
			this.taskCallback = taskCallback;
            this.taskRunParam=taskRunParam;
			this.context = context;

		}

		@Override
		public void run() {

			Date startTime = new Date();

			try {
				registerThread(taskRunParam.getExecId(), task);
				
//				TaskContext c = SerializationUtils.clone();

				task.start(taskRunParam, context);


				if (!task.isSuccess()) {
					String status = "4";
					if (task.isInterrupted()) {
						status = "5";
					}
					taskCallback.handler(startTime, new Date(), status, taskRunParam.getLogFileName(), taskRunParam.getExecId());
				} else {
					taskCallback.handler(startTime, new Date(), "2", taskRunParam.getLogFileName(), taskRunParam.getExecId());
				}
			} finally {
				removeThread(taskRunParam.getExecId());
			}

		}

	}

	public TaskContainer(Integer threadSize) {
		mainPool = Executors.newFixedThreadPool(threadSize, new ThreadFactory() {
			@Override
			public Thread newThread(Runnable r) {
				// TODO Auto-generated method stub
				Thread thread = new Thread(r);
				thread.setName("datagrid-taskContainer-" + index.getAndIncrement());
				return thread;
			}
		});
	}

	private Map<String, ExecCache> threadCacheMap = new ConcurrentHashMap();

	@Data
	public class ExecCache {

		private String execId;
		private Task task;

		public ExecCache(String execId, Task task) {
			this.execId = execId;
			this.task = task;
		}
	}

	public void registerThread(String execId, Task task) {
		threadCacheMap.put(execId, new ExecCache(execId, task));
	}

	private void interruptedThread(String execId) {

		if (threadCacheMap.containsKey(execId)) {
			threadCacheMap.get(execId).getTask().shutdownNow();
		}

	}

	public void removeThread(String execId) {
		threadCacheMap.remove(execId);
	}

	public void execute(Task task, TaskContext context,TaskRunParam taskRunParam,TaskCallback taskCallback) {
		// TODO Auto-generated method stub
		mainPool.execute(new TaskRunnable(task, context, taskRunParam,taskCallback));
	}

	/**
	 * @Title: interrupted
	 * @Description: TODO(描述)
	 * @param string
	 * @author liuyi
	 * @date 2023-04-19 10:52:56
	 */
	public void interrupted(String execId) {
		// TODO Auto-generated method stub
		interruptedThread(execId);

	}

}
